<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>jQuery tablesorter 2.0 - Mark Widget</title>

	<!-- jQuery -->
	<script src="js/jquery-latest.min.js"></script>

	<!-- Demo stuff -->
	<link class="ui-theme" rel="stylesheet" href="css/jquery-ui.min.css">
	<script src="js/jquery-ui.min.js"></script>
	<link rel="stylesheet" href="css/jq.css">
	<link href="css/prettify.css" rel="stylesheet">
	<script src="js/prettify.js"></script>
	<script src="js/docs.js"></script>

	<!-- Tablesorter: required -->
	<link rel="stylesheet" href="../css/theme.blue.css">
	<style id="css">/* Example showing how to change the mark color by column */
tr td:nth-child(1) mark { background: #aa0000; color: #fff; }
tr td:nth-child(2) mark { background: #00aa00; color: #fff; }
tr td:nth-child(3) mark { background: #0000aa; color: #fff; }
tr td:nth-child(4) mark { background: #aaaa00; color: #fff; }
tr td:nth-child(5) mark { background: #00aaaa; color: #fff; }
tr td:nth-child(6) mark { background: #aa00aa; color: #fff; }
</style>
	<script src="../js/jquery.tablesorter.js"></script>
	<script src="../js/widgets/widget-filter.js"></script>

	<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/7.0.2/jquery.mark.js"></script>
	<script src="../js/widgets/widget-mark.js"></script>

	<script id="js">$(function() {

	// ==============================
	// WITH filter widget
	// ==============================
	var $table = $('#table').tablesorter({
		theme: 'blue',
		widthFixed : true,
		// sort & filter diacritics
		sortLocaleCompare: true,
		widgets: ['zebra', 'filter', 'mark'],
		widgetOptions: {
			filter_external: 'input[name="keyword"]',
			filter_reset: 'button.reset',

			// default settings
			mark_accuracy: 'partially',
			mark_className: '',
			mark_debug: false,
			mark_diacritics: true,
			mark_element: 'mark',
			mark_exclude: [],
			mark_iframes: false,
			mark_log: console,
			mark_separateWordSearch: true,
			mark_synonyms: {},
			// callback functions
			mark_done: function(totalMatches) {},
			mark_each: function(element) {},
			mark_filter: function(node, term, counter, totalCounter) { return true; },
			mark_noMatch: function(keyword) {}
		}
	});

	// preset searches for the first table
	$('button[data-filter-column]').click(function(){
		var filters = [],
			$t = $(this),
			col = $t.data('filter-column'), // zero-based index, or "all" column
			txt = $t.data('filter-text') || $t.text(); // text to add to filter
		filters[col === "all" ? $table[0].config.columns : col] = txt;
		$.tablesorter.setFilters( $table, filters );
		return false;
	});

	// ==============================
	// NO filter widget
	// ==============================
	var $table2 = $('#table2').tablesorter({
		theme: 'blue',
		widthFixed : true,
		// sort & filter diacritics
		sortLocaleCompare: true,
		widgets: ['zebra', 'mark'],
		widgetOptions : {
			// default settings
			mark_accuracy: 'partially',
			mark_className: '',
			mark_debug: false,
			mark_diacritics: true,
			mark_element: 'mark',
			mark_exclude: [],
			mark_iframes: false,
			mark_log: console,
			mark_separateWordSearch: true,
			mark_synonyms: {},
			// callback functions
			mark_done: function(totalMatches) {},
			mark_each: function(element) {},
			mark_filter: function(node, term, counter, totalCounter) { return true; },
			mark_noMatch: function(keyword) {}
		}
	});

	// preset searches on the second table
	$('button.table2').click(function(){
		// check for reset
		var query = $(this).hasClass('reset2') ? '' : this.textContent;
		$('#table2-search')
			.val(query)
			.trigger('input');
	});

	$('#table2-search').on('input', function() {
		var config = $table2[0].config,
			filters = [];
		// still target the "any" match column
		filters[config.columns] = this.value;
		// trigger a mark update
		$table2.trigger('markUpdate', [filters]);
		// or call the function directly
		// $.tablesorter.mark.update(config, filters);
	});

});</script>

</head>
<body>
<div id="banner">
	<h1>table<em>sorter</em></h1>
	<h2>Mark Widget</h2>
	<h3>Flexible client-side table sorting</h3>
	<a href="index.html">Back to documentation</a>
</div>
<div id="main">

	<p></p>
	<br>
	<div id="root" class="accordion">

		<h3 id="notes"><a href="#">Notes</a></h3>
		<div>
			<ul>
				<li>Added <span class="verison">v2.27.0</span> for use with the <a href="https://markjs.io/">mark.js</a> plugin.</li>
				<li>Notable Issues:
					<ul>
						<li><button class="bad" type="button" data-filter-column="all">~ae</button> - Some rows won't be highlighted because the filter finds fuzzy matches across rows, while the mark widget is targeting separate cell content.</li>
						<li><button type="button" data-filter-column="all">/(aaron|bruce)/i</button> - Using a regular expression search will not include diacritics; use an " OR " search instead <button type="button" data-filter-column="all">aaron|bruce</button>.<br>
						I may fix this in future updates.
						</li>
						<li><button class="bad" type="button" data-filter-column="all">/.*/</button> or <button class="bad" type="button" data-filter-column="all">/(|)/</button> - When a regular expression matches everything, the regex is ignored by the mark widget otherwise, <a href="https://github.com/julmot/mark.js/issues/55">mark.js does bad things</a>; but this regex is okay: <button type="button" data-filter-column="all">/.+/</button>.</li>
						<li><button class="bad" type="button" data-filter-column="3"><=22</button> or <button class="bad" type="button" data-filter-column="5">10 - 20</button> - Operators &amp; ranges are not fully supported (these are not supported at all by the filter widget in an "all" columns match - see the documentation on <a href="example-widget-filter-any-match.html#limitations">any match limitations</a>).</li>
						<li><button class="bad" type="button" data-filter-column="all">!aaron</button> - There is nothing to highlight for not matches.</li>
					</ul>
				</li>
				<li>The <a href="https://markjs.io/#mark"><code>mark</code> function</a> is used for the following filter queries:
					<ul>
						<li>Plain text</li>
						<li>Logical AND (<code>&nbsp;and&nbsp;</code> or <code>&nbsp;&&&nbsp;</code>) &amp; logical OR (<code>&nbsp;or&nbsp;</code> or <code>|</code>) searches.</li>
						<li>Invalid regex (e.g. <code>/(|)/</code>).</li>
						<li>Operator, range, exact and not searches.</li>
					</ul>
				</li>
				<li>The <a href="https://markjs.io/#markregexp"><code>markRegExp</code> function</a> is used when the filter contains:
					<ul>
						<li>A "valid" regular expression</li>
						<li>Fuzzy search (<code>~</code>)</li>
						<li>Wild card <code>?</code> or <code>*</code> search</li>
					</ul>
				</li>

				<li>Try out the <a href="http://jsfiddle.net/Mottie/odyfw8Lj/">jSFiddle Playground</a>.</li>
			</ul>
		</div>

		<h3><a href="#">Options</a></h3>
		<div>
			<h4>Mark widget defaults (added inside of tablesorter <code>widgetOptions</code>)</h4>
			<h5>The widgetOptions are essentially Mark.js settings with a <code>mark_</code> prefix. All options are dynamically updated.</h5>
			<div>
				<span class="label label-info">TIP!</span> Click on the link in the function column to reveal full details (or <a href="#" class="toggleAll">toggle</a>|<a href="#" class="showAll">show</a>|<a href="#" class="hideAll">hide</a> all) or double click to update the browser location.
			</div>
			<table class="options tablesorter-blue" data-sortlist="[[0,0]]">
				<thead>
					<tr><th>Option</th><th>Default</th><th class="sorter-false">Description</th></tr>
				</thead>
				<tbody>

					<tr id="mark-tsupdateclass">
						<td><a href="#" class="permalink">mark_tsUpdate</a></td>
						<td>"markUpdate"</td>
						<td>This option sets the event that can be triggered on the table to update the marks.
							<div class="collapsible">
							<br>
								Use it as follows:
								<pre class="prettyprint lang-js">$('table').tablesorter({
  widgets: ['mark'],
  widgetOptions: {
    mark_tsUpdate: 'markFu'
  }
});

$('button.update').click(function(){
  // update the marks in the table
  $('table').trigger('markFu');
});</pre>
						</div>
						</td>
					</tr>
				</tbody>
				<tbody class="tablesorter-infoOnly">
					<tr>
						<th colspan="3">Mark.js settings - see <a href="https://markjs.io/#api">official documentation</a></th>
					</tr>
				</tbody>

				<tbody>
					<tr id="mark-element">
						<td><span class="permalink">mark_element</span></td>
						<td>"mark"</td>
						<td>HTML element to wrap matches.</td>
					</tr>
					<tr id="mark-classname">
						<td><span class="permalink">mark_className</span></td>
						<td>""</td>
						<td>A class name added to the element.</td>
					</tr>
					<tr id="mark-exclude">
						<td><span class="permalink">mark_exclude</span></td>
						<td>[]</td>
						<td>An array with exclusion selectors. Matches inside these elements will be ignored.</td>
					</tr>
					<tr id="mark-separatewordsearch">
						<td><span class="permalink">mark_separateWordSearch</span></td>
						<td>true</td>
						<td>Whether to search for each word separated by a blank.</td>
					</tr>
					<tr id="mark-accuracy">
						<td><span class="permalink">mark_accuracy</span></td>
						<td>"partially"</td>
						<td>Use "partially", "complementary", "exactly" or object - see markjs docs for details.</td>
					</tr>
					<tr id="mark-diacritics">
						<td><span class="permalink">mark_diacritics</span></td>
						<td>true</td>
						<td>If <code>true</code>, diacritic characters should be matched.</td>
					</tr>
					<tr id="mark-synonyms">
						<td><span class="permalink">mark_synonyms</span></td>
						<td>{}</td>
						<td>An object with synonyms..</td>
					</tr>
					<tr id="mark-iframes">
						<td><span class="permalink">mark_iframes</span></td>
						<td>false</td>
						<td>Whether to search also inside iframes.</td>
					</tr>
					<tr id="mark-each">
						<td><span class="permalink">mark_each</span></td>
						<td>function(element){}</td>
						<td>A callback for each marked element.</td>
					</tr>
					<tr id="mark-filter">
						<td><a href="#" class="permalink">mark_filter</a></td>
						<td>function(parameters){ return true; }</td>
						<td>A callback to filter or limit matches.
							<div class="collapsible">
								<br>
								When the <code>mark</code> function is called, the function parameters are:
								<pre class="prettyprint lang-js">function(node, keyword, matches, totalMatches) { return true; }</pre>
								When the <code>markRegExp</code> function is called, the function parameters are:
								<pre class="prettyprint lang-js">function(node, match, totalMatches) { return true; }</pre>
								<p>In both cases, a <code>return true</code> is needed to highlight the match.</p>
								<span class="label label-info">Note</span> See the notes section above to know when which function is called.
							</div>
						</td>
					</tr>
					<tr id="mark-nomatch">
						<td><a href="#" class="permalink">mark_noMatch</a></td>
						<td>function(keyword){}</td>
						<td>A callback function that will be called when there are no matches.
							<div class="collapsible">
								<br>
								When the <code>mark</code> function is called, the keyword parameter is a string.
								<p>When the <code>markRegExp</code> function is called, the keyword parameter is the regular expression.</p>
								<span class="label label-info">Note</span> See the notes section above to know when which function is called.
							</div>
						</td>
					</tr>
					<tr id="mark-done">
						<td><span class="permalink">mark_done</span></td>
						<td>function(totalMatches){}</td>
						<td>A callback function after all marks are done.</td>
					</tr>
					<tr id="mark-debug">
						<td><span class="permalink">mark_debug</span></td>
						<td>false</td>
						<td>If <code>true</code>, messages will be logged.</td>
					</tr>
					<tr id="mark-log">
						<td><span class="permalink">mark_log</span></td>
						<td>console</td>
						<td>Log message to this object.</td>
					</tr>
				</tbody>
			</table>
		</div>

	</div>
	<p></p>

	<h1>Demo: With the Filter Widget</h1>
	<br>
	Search/Highlight all columns: <input type="text" name="keyword" data-column="all">
	<button type="button" class="reset">Reset</button>
	<button type="button" data-filter-column="all">13</button>
	<button class="bad" type="button" data-filter-column="all" title="See &quot;Notes&quot; on why the second row isn't highlighted">~ee</button>
	<button type="button" data-filter-column="all">br?n</button>
	<button type="button" data-filter-column="all">br*n</button>
	<button type="button" data-filter-column="all">aaron|bruce</button>
	<button type="button" data-filter-column="all">aaron && 2</button>
	<table id="table" class="tablesorter">
		<thead>
			<tr>
				<th>Rank</th>
				<th class="filter-match">First Name</th>
				<th>Last Name</th>
				<th>Age</th>
				<th>Total</th>
				<th>Discount</th>
				<th>Date</th>
			</tr>
		</thead>
		<tbody>
			<tr><td>1</td><td>Philip Aaron Wong</td><td>Johnson Sr Esq</td><td>25</td><td>$5.95</td><td>22%</td><td>Jun 26, 2004 7:22 AM</td></tr>
			<tr><td>11</td><td>Aáron</td><td>Hibert</td><td>12</td><td>$2.99</td><td>5%</td><td>Aug 21, 2009 12:21 PM</td></tr>
			<tr><td>12</td><td>Brandon Clark</td><td>Henry Jr</td><td>51</td><td>$42.29</td><td>18%</td><td>Oct 13, 2000 1:15 PM</td></tr>
			<tr><td>111</td><td>Peter</td><td>Párker</td><td>28</td><td>$9.99</td><td>20%</td><td>Jul 6, 2006 8:14 AM</td></tr>
			<tr><td>21</td><td>John</td><td>Hood</td><td>33</td><td>$19.99</td><td>25%</td><td>Dec 10, 2002 5:14 AM</td></tr>
			<tr><td>013</td><td>Clark</td><td>Kènt Sr.</td><td>18</td><td>$15.89</td><td>44%</td><td>Jan 12, 2003 11:14 AM</td></tr>
			<tr><td>005</td><td>Bruce</td><td>Almighty Esq</td><td>45</td><td>$153.19</td><td>44%</td><td>Jan 18, 2021 9:12 AM</td></tr>
			<tr><td>10</td><td>Alex</td><td>Dumāss</td><td>13</td><td>$5.29</td><td>4%</td><td>Jan 8, 2012 5:11 PM</td></tr>
			<tr><td>16</td><td>Jim</td><td>Franco</td><td>24</td><td>$14.19</td><td>14%</td><td>Jan 14, 2004 11:23 AM</td></tr>
			<tr><td>166</td><td>Brüce Lee</td><td>Evans</td><td>22</td><td>$13.19</td><td>11%</td><td>Jan 18, 2007 9:12 AM</td></tr>
			<tr><td>100</td><td>Brenda Dexter</td><td>McMasters</td><td>18</td><td>$55.20</td><td>15%</td><td>Feb 12, 2010 7:23 PM</td></tr>
			<tr><td>55</td><td>Dennís</td><td>Bronson</td><td>65</td><td>$123.00</td><td>32%</td><td>Jan 20, 2001 1:12 PM</td></tr>
			<tr><td>9</td><td>Martha</td><td>delFuego</td><td>25</td><td>$22.09</td><td>17%</td><td>Jun 11, 2011 10:55 AM</td></tr>
		</tbody>
	</table>

	<h1>Demo: Without the Filter Widget</h1>
	<br>
	Search/Highlight all columns: <input id="table2-search" type="search">
	<button class="table2 reset2" type="button">Reset</button>
	<button class="table2" type="button">13</button>
	<button class="table2 bad" type="button" title="See &quot;Notes&quot; on why the &quot;005 Bruce Almighty&quot; row isn't highlighted">~ee</button>
	<button class="table2" type="button">br?n</button>
	<button class="table2" type="button">br*n</button>
	<button class="table2" type="button">aaron|bruce</button>
	<button class="table2" type="button">aaron && 2</button>

	<table id="table2" class="tablesorter">
		<thead>
			<tr>
				<th>Rank</th>
				<th class="filter-match">First Name</th>
				<th>Last Name</th>
				<th>Age</th>
				<th>Total</th>
				<th>Discount</th>
				<th>Date</th>
			</tr>
		</thead>
		<tbody>
			<tr><td>1</td><td>Philip Aaron Wong</td><td>Johnson Sr Esq</td><td>25</td><td>$5.95</td><td>22%</td><td>Jun 26, 2004 7:22 AM</td></tr>
			<tr><td>11</td><td>Aáron</td><td>Hibert</td><td>12</td><td>$2.99</td><td>5%</td><td>Aug 21, 2009 12:21 PM</td></tr>
			<tr><td>12</td><td>Brandon Clark</td><td>Henry Jr</td><td>51</td><td>$42.29</td><td>18%</td><td>Oct 13, 2000 1:15 PM</td></tr>
			<tr><td>111</td><td>Peter</td><td>Párker</td><td>28</td><td>$9.99</td><td>20%</td><td>Jul 6, 2006 8:14 AM</td></tr>
			<tr><td>21</td><td>John</td><td>Hood</td><td>33</td><td>$19.99</td><td>25%</td><td>Dec 10, 2002 5:14 AM</td></tr>
			<tr><td>013</td><td>Clark</td><td>Kènt Sr.</td><td>18</td><td>$15.89</td><td>44%</td><td>Jan 12, 2003 11:14 AM</td></tr>
			<tr><td>005</td><td>Bruce</td><td>Almighty Esq</td><td>45</td><td>$153.19</td><td>44%</td><td>Jan 18, 2021 9:12 AM</td></tr>
			<tr><td>10</td><td>Alex</td><td>Dumāss</td><td>13</td><td>$5.29</td><td>4%</td><td>Jan 8, 2012 5:11 PM</td></tr>
			<tr><td>16</td><td>Jim</td><td>Franco</td><td>24</td><td>$14.19</td><td>14%</td><td>Jan 14, 2004 11:23 AM</td></tr>
			<tr><td>166</td><td>Brüce Lee</td><td>Evans</td><td>22</td><td>$13.19</td><td>11%</td><td>Jan 18, 2007 9:12 AM</td></tr>
			<tr><td>100</td><td>Brenda Dexter</td><td>McMasters</td><td>18</td><td>$55.20</td><td>15%</td><td>Feb 12, 2010 7:23 PM</td></tr>
			<tr><td>55</td><td>Dennís</td><td>Bronson</td><td>65</td><td>$123.00</td><td>32%</td><td>Jan 20, 2001 1:12 PM</td></tr>
			<tr><td>9</td><td>Martha</td><td>delFuego</td><td>25</td><td>$22.09</td><td>17%</td><td>Jun 11, 2011 10:55 AM</td></tr>
		</tbody>
	</table>

	<h1>Page Header</h1>
	<div>
		<pre class="prettyprint lang-html">&lt;!-- blue theme stylesheet --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/theme.blue.css&quot;&gt;
&lt;!-- tablesorter plugin --&gt;
&lt;script src=&quot;js/jquery-latest.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/jquery.tablesorter.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/jquery.tablesorter.widgets.js&quot;&gt;&lt;/script&gt;

&lt;!-- jquery.mark.js & tablesorter mark widget loaded after the plugin --&gt;
&lt;script src=&quot;js/jquery.mark.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/widget-mark.js&quot;&gt;&lt;/script&gt;</pre>
	</div>

	<h1>CSS</h1>
	<div id="css">
		<pre class="prettyprint lang-css"></pre>
	</div>

	<h1>Javascript</h1>
	<div id="javascript">
		<pre class="prettyprint lang-javascript"></pre>
	</div>

</div>

</body>
</html>
